package com.bj58.mis.apm.server.kylin.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.http.fileupload.FileUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * zip工具包
 * @author wxw
 */
public class ZipUtil {
    /**
     * 日志输出对象
     */
    static Log log = LogFactory.getLog(ZipUtil.class);

    /**
     * zip打包文件
     * @param sourcePath 需要打包的根目录或文件，如果为目录则打包子文件，如果为文件直接打包
     * @param zipFilePath 打包文件
     * @throws Exception
     */
    public static void zip(String sourcePath, String zipFilePath) throws IOException{
        log.debug("start zip file , sourcePath = : " + sourcePath);
        File source = new File(sourcePath);
        if (source.exists()) {
            List<ZipEntry> list = foreach(source);
            File target = new File(zipFilePath);
            if (target.exists()) {
                target.delete(); // 删除旧的文件
            }
            ZipOutputStream zos = null;
            try {
                zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath)));
                for (ZipEntry en : list) {
                    File fo = new File(source.getParent(), en.getName());
                    zos.putNextEntry(en);
                    FileInputStream in = new FileInputStream(fo);
                    byte[] buffer = new byte[1024*8];
                    for(int len=0;(len=in.read(buffer))!=-1;){
                        zos.write(buffer, 0, len);
                    }
                    in.close();
                    zos.flush();
                }
                zos.close();
                log.debug("end zip file : " + zipFilePath);
            }catch (IOException e){
                log.debug("zip file error:");
                log.debug(e.getMessage());
                throw e;
            }
        }
    }

    public static String unzip(String zipFilePath) throws IOException{
        String pullPath = zipFilePath.substring(0, zipFilePath.length() - 4) + File.separator;
        unzip(zipFilePath, pullPath);
        return pullPath;
    }
    /**
     * 解压缩，将zip包中的文件进行解压
     * @param zipFilePath zip文件路径
     * @param pullPath 解压缩目的路径
     * @throws Exception
     */
    public static void unzip(String zipFilePath, String pullPath) throws IOException{
        // 读取压缩文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));
        log.debug("start uzip file : " + zipFilePath);
        ZipInputStream zin = null;

        File pullDir = new File(pullPath);
        if(pullDir.exists()){
            FileUtils.deleteDirectory(pullDir);
        }

        ZipEntry entry;
        File targetFold = null;
        try {
            zin = new ZipInputStream(bis);
            while ((entry = zin.getNextEntry()) != null) {
                // 设置解压输出文件
                int BUFFER = 2048;
                String tmp = pullPath +  entry.getName();
                //create file
                targetFold = new File(tmp);

                if(targetFold.isDirectory()){
                    targetFold.mkdirs();
                    continue;
                }else if(!targetFold.getParentFile().exists()){
                    targetFold.getParentFile().mkdirs();
                }

                FileOutputStream fos = new FileOutputStream(targetFold);

                BufferedOutputStream dest = new BufferedOutputStream(fos,BUFFER);

                // 读取文件
                int count = 0;
                byte[] data = new byte[BUFFER];
                while ((count = zin.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, count);
                }
                dest.flush();// 刷新写入数据
                dest.close();// 关闭输出流
            }
            zin.close(); // 关闭输入流
            log.debug("end uzip file , pullPath = " + pullPath);
        } catch (Exception e) {
            log.debug("uzip file error:");
            log.debug(e.getMessage());
            throw e;
        } finally {
            if(zin != null)
                zin.close();
        }
    }

    /**
     * 获取文件下的子文件
     * @param file
     * @return
     */
    private static List<ZipEntry> foreach(File file) {
        List<ZipEntry> list = new ArrayList();
        if (file.isDirectory()) {
            for (File fo : file.listFiles()) {
                foreach(fo, "", list);
            }
        } else if (file.isFile()) {
            list.add(new ZipEntry("" + file.getName()));
        }
        return list;
    }

    /**
     * 获取文件下的子文件，递归
     * @param file
     * @param path
     * @param list
     */
    private static void foreach(File file, String path, List<ZipEntry> list) {
        if (file.isDirectory()) {
            path += file.getName() + File.separator;
            for (File fo : file.listFiles()) {
                foreach(fo, path, list);
            }
        } else if (file.isFile()) {
            list.add(new ZipEntry(path + file.getName()));
        }
    }

    public static void main(String[] args) throws Exception {
        /**/
        String zipfile = "D:\\temp\\kybot_2018_06_01_11_18_58_B46850.zip";
        String fullpath = "D:\\temp\\kybot_2018_06_01_11_18_58_B46850\\";
        unzip(zipfile, fullpath);

        /*
        String sourcepath = "D:\\temp\\kybot_2018_05_24_13_48_20_B39AEF.zip";
        String zipfile = "D:\\temp\\kybot_2018_05_24_13_48_20_01.zip";
        zip(sourcepath, zipfile);
*/
    }
}
